
'use strict';

/**
	Part of Zombie Navigator
	Copyright © 2015  Zombie Navigator Developers
	
	@file
	@module
	@license AGPL-3.0+
*/


/*
	This is an internal module used inside the abstraction wrapper.
*/


/* Addon SDK dependencies */
const _sdkTabs = require('sdk/tabs');
const _sdkLoadReason = require('sdk/self').loadReason + '';


/* Used modules */
const _modNotification = require('../notification');


/* Private properties */
let _openCount = 0, _readyCount = 0, _manyOpenTabs = false, _startTime = (new Date).getTime();
let _readyCallbacks = new Set;

const _isIgnorableLoad = () => {
	// Ignore page loads *once* within < 200ms since startup
	return 'startup' == _sdkLoadReason && 200 > ((new Date).getTime() - _startTime);
};

_sdkTabs.on('open', sdkTab => {
	_openCount++;
});

_sdkTabs.on('ready', sdkTab => {
	if (_isIgnorableLoad()) {
		return;
	}
	for (let callback of _readyCallbacks) {
		callback(sdkTab);
	}
	_readyCount++;
});


/* Exported APIs */

/**
	@protected
	@returns {object}
*/
const openWindowTracker = () => {
	const sdkTabs = _sdkTabs;
	if (1 < sdkTabs.length) {
		_manyOpenTabs = true;
	}
	
	let openCount = 0, readyCount = 0;
	
	const tracker = {
		get openCount () {
			return openCount;
		}
		,
		get readyCount () {
			return readyCount;
		}
		, addWindow (sdkWindow) {
			sdkWindow.tabs.on('open', sdkTab => {
				openCount++;
			});
			
			const callback = sdkTab => {
				if (sdkTab.window == sdkWindow) {
					readyCount++;
				}
			};
			
			_readyCallbacks.add(callback);
			sdkWindow.once('close', sdkWindow => {
				_readyCallbacks.delete(callback);
			});
		}
	};
	return tracker;
};

/**
	Check the absence of user activities before shutdown
	@protected
	@returns {boolean}
*/
const isSessionClean = (... windowTrackers) => {
	try {
		if (_manyOpenTabs) {
			throw 'Many open tabs on startup';
		}
		
		let openCount = 0, readyCount = 0;
		for (let tracker of windowTrackers) {
			if (!tracker) continue;
			openCount += tracker.openCount || 0;
			readyCount += tracker.readyCount || 0;
		}
		
		if (_openCount > openCount) {
			throw 'User opened one or more windows';
		}
		if (_readyCount > readyCount) {
			throw 'Some contents have been loaded';
		}
	} catch (e) {
		const modNotification = _modNotification;
		modNotification.showNotification('Script finished but the browser cannot be closed. Reason: ' + e);
		
		return false;
	}
	
	return true;
};


/* Exports */
exports.openWindowTracker = openWindowTracker;
exports.isSessionClean = isSessionClean;


// vim: ts=4 noet ai

